#include "stdafx.h"
#include "MiniBasicImpl.h"
#include "MiniImplFactory.h"
#include "MiniBasic_h.h"
#include "GlobalVariables.h"
#include "HelperStructs.h"
#include "Registration.h"

BOOL APIENTRY DllMain(HINSTANCE, DWORD dwReason, LPVOID)
{
    BOOL bRet = TRUE;
    switch(dwReason)
    {
        case DLL_PROCESS_ATTACH:
        {
            DWORD temp = TlsAlloc();
            if(temp != TLS_OUT_OF_INDEXES)
            {
                tlsSlotIndex = temp;
            }
            else
            {
                bRet = FALSE;
            }
        }
        break;
        case DLL_PROCESS_DETACH:
        {
            TlsFree(tlsSlotIndex);
        }
        break;
    }
    return bRet;
}

STDAPI DllRegisterServer()
{
    ComInitializer com;
    HRESULT hr = S_OK;
    ITypeLib* pTypeLib = NULL;
    std::wstring pathToTypeLib;
    try
    {
        pathToTypeLib = MiniBasicImpl::GetFullTypeLibPath();
    }
    catch(const std::runtime_error&)
    {
        return E_FAIL;
    }
    if(SUCCEEDED(hr = LoadTypeLib(pathToTypeLib.c_str(), &pTypeLib)))
    {
        hr = RegisterTypeLib(pTypeLib, pathToTypeLib.c_str(), NULL);
        if(SUCCEEDED(hr))
        {
            hr = CreateRegistryEntries(CLSID_MiniBasicImpl, L"MiniBasic.Parser", pTypeLib, L"MiniBasic Parser");
        }
        pTypeLib->Release();
    }
    return hr;
}

STDAPI DllUnregisterServer()
{
    ComInitializer com;
    HRESULT hr = S_OK;
#ifdef _WIN64
    const SYSKIND os = SYS_WIN64;
#else
    const SYSKIND os = SYS_WIN32;
#endif
    ITypeLib* pTypeLib = NULL;
    std::wstring pathToTypeLib;
    try
    {
        pathToTypeLib = MiniBasicImpl::GetFullTypeLibPath();
    }
    catch(const std::runtime_error&)
    {
        return E_FAIL;
    }
    if(SUCCEEDED(LoadTypeLib(pathToTypeLib.c_str(), &pTypeLib)))
    {
        hr = RemoveRegistryEntries(CLSID_MiniBasicImpl, L"MiniBasic.Parser", pTypeLib);
        pTypeLib->Release();
        if(SUCCEEDED(hr))
        {
            hr = UnRegisterTypeLib(LIBID_MiniLib, 1, 0, 0, os);
        }        
    }
    return hr;
}

STDAPI DllGetClassObject(REFIID clsid, REFIID riid, LPVOID* ppv)
{
    HRESULT hr = S_OK;
    if(ppv)
    {
        if(clsid == CLSID_MiniBasicImpl)
        {
            MiniImplFactory* pFact = new (std::nothrow)MiniImplFactory;
            if(pFact)
            {
                hr = pFact->QueryInterface(riid, ppv);
                pFact->Release();
            }
            else
            {
                hr = E_OUTOFMEMORY;
            }
        }
        else
        {
            hr = CLASS_E_CLASSNOTAVAILABLE;
        }
    }
    else
    {
        hr = E_POINTER;
    }
    return hr;
}

STDAPI DllCanUnloadNow()
{
    return globalRefCount == 0 ? S_OK : S_FALSE;
}

//#define MAKE_ME_AN_EXE
#ifdef MAKE_ME_AN_EXE

#include <shellapi.h>
#include <tchar.h>

//int __cdecl wmain(int argc, WCHAR* argv[])
int WINAPI _tWinMain(HINSTANCE, HINSTANCE, LPTSTR lpcmd, int)
{
    //int argNum = 0;
    //LPWSTR* argv = CommandLineToArgvW(lpcmd, &argNum);
    BSTR bstr = SysAllocString(lpcmd);
    MiniBasicImpl impl;
    ExecutionParameters params = {0};
    params.pathToFile = bstr;
    params.keepConsoleOpen = true;
    impl.ExecuteFile(&params);
    SysFreeString(bstr);
    //LocalFree(argv);
    return 0;
}

#endif